package cn.stylefeng.guns.modular.gridsystem.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.stylefeng.guns.core.context.login.LoginContextHolder;
import cn.stylefeng.guns.core.factory.PageFactory;
import cn.stylefeng.guns.core.pojo.page.PageResult;
import cn.stylefeng.guns.core.pojo.response.ErrorResponseData;
import cn.stylefeng.guns.core.pojo.response.ResponseData;
import cn.stylefeng.guns.core.pojo.response.SuccessResponseData;
import cn.stylefeng.guns.modular.gridsystem.constants.SysRoleConstant;
import cn.stylefeng.guns.modular.gridsystem.entity.BizDevice;
import cn.stylefeng.guns.modular.gridsystem.entity.BizFaultModel;
import cn.stylefeng.guns.modular.gridsystem.entity.BizIndustryInvolved;
import cn.stylefeng.guns.modular.gridsystem.entity.BizStation;
import cn.stylefeng.guns.modular.gridsystem.mapper.BizFaultModelMapper;
import cn.stylefeng.guns.modular.gridsystem.model.param.BizFaultModelParam;
import cn.stylefeng.guns.modular.gridsystem.model.param.RegisterParam;
import cn.stylefeng.guns.modular.gridsystem.service.BizDeviceService;
import cn.stylefeng.guns.modular.gridsystem.service.BizFaultModelService;
import cn.stylefeng.guns.modular.gridsystem.service.BizIndustryInvolvedService;
import cn.stylefeng.guns.modular.gridsystem.service.BizStationService;
import cn.stylefeng.guns.modular.gridsystem.utils.CollectorConfigUtil;
import cn.stylefeng.guns.modular.gridsystem.utils.EngineUtil;
import cn.stylefeng.guns.modular.gridsystem.utils.MyFileUtils;
import cn.stylefeng.guns.sys.modular.file.result.SysFileInfoResult;
import cn.stylefeng.guns.sys.modular.file.service.SysFileInfoService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.File;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * biz_fault_model 服务实现类
 *
 * @author ssy
 * @date 2021/11/01 16:44
 */
@Slf4j
@Service
public class BizFaultModelServiceImpl extends ServiceImpl<BizFaultModelMapper, BizFaultModel> implements BizFaultModelService {

    @Resource
    private BizStationService bizStationService;
    @Resource
    private BizDeviceService bizDeviceService;
    @Resource
    private BizIndustryInvolvedService bizIndustryInvolvedService;
    @Resource
    private SysFileInfoService sysFileInfoService;

    /**
     * 分页查询biz_fault_model
     *
     * @param bizFaultModelParam
     * @return
     */
    @Override
    public PageResult<BizFaultModel> page(BizFaultModelParam bizFaultModelParam) {
        // 构造条件
        LambdaQueryWrapper<BizFaultModel> queryWrapper = new LambdaQueryWrapper<>();
        // 查询分页结果
        return new PageResult<>(this.page(PageFactory.defaultPage(), queryWrapper));
    }

    /**
     * 查询所有biz_fault_model
     *
     * @param bizFaultModelParam
     * @return
     */
    @Override
    public List<BizFaultModel> list(BizFaultModelParam bizFaultModelParam) {
        // 构造条件
        LambdaQueryWrapper<BizFaultModel> queryWrapper = new LambdaQueryWrapper<>();
        if (ObjectUtil.isNotNull(bizFaultModelParam)) {
            if (ObjectUtil.isNotEmpty(bizFaultModelParam.getId())) {
                queryWrapper.eq(BizFaultModel::getId, bizFaultModelParam.getId());
            }
            if (ObjectUtil.isNotEmpty(bizFaultModelParam.getGroupId())) {
                queryWrapper.eq(BizFaultModel::getGroupId, bizFaultModelParam.getGroupId());
            }
            if (ObjectUtil.isNotEmpty(bizFaultModelParam.getFaultLevel())) {
                queryWrapper.eq(BizFaultModel::getFaultLevel, bizFaultModelParam.getFaultLevel());
            }
        }
        return this.list(queryWrapper);
    }

    /**
     * 添加biz_fault_model
     *
     * @param bizFaultModelParam
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(BizFaultModelParam bizFaultModelParam) {
        if (ObjectUtil.isEmpty(bizFaultModelParam.getRegisterStatus())) {
            bizFaultModelParam.setRegisterStatus(0);
        }
        // 将dto转为实体
        BizFaultModel bizFaultModel = new BizFaultModel();
        BeanUtil.copyProperties(bizFaultModelParam, bizFaultModel);
        this.save(bizFaultModel);
    }

    @Override
    public ResponseData addNew(BizFaultModelParam bizFaultModelParam) {
        List<BizFaultModel> list = getListByAccessToken(bizFaultModelParam.getAccessToken());
        if (list != null && list.size() > 0) {
            return new ResponseData(false, 201, "故障编号已存在，不能重复", null);
        }
        // 将dto转为实体
        BizFaultModel bizFaultModel = new BizFaultModel();
        BeanUtil.copyProperties(bizFaultModelParam, bizFaultModel);

        this.save(bizFaultModel);
        return new SuccessResponseData();
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(BizFaultModelParam bizFaultModelParam) {
        this.removeById(bizFaultModelParam.getId());
    }

    /**
     * 编辑biz_fault_model
     *
     * @param bizFaultModelParam
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void edit(BizFaultModelParam bizFaultModelParam) {
        // 根据id查询实体
        BizFaultModel bizFaultModel = this.queryBizFaultModel(bizFaultModelParam);
        // 请求参数转化为实体
        BeanUtil.copyProperties(bizFaultModelParam, bizFaultModel);
        this.updateById(bizFaultModel);
    }

    @Override
    public ResponseData editNew(BizFaultModelParam bizFaultModelParam) {

        List<BizFaultModel> list = getListByAccessTokenForEdit(bizFaultModelParam.getAccessToken(), bizFaultModelParam.getId());
        if (list != null && list.size() > 0) {
            return new ResponseData(false, 201, "故障编号已存在，不能重复", null);
        }
        // 将dto转为实体
        BizFaultModel bizFaultModel = new BizFaultModel();
        BeanUtil.copyProperties(bizFaultModelParam, bizFaultModel);

        this.updateById(bizFaultModel);
        return new SuccessResponseData();
    }


    @Override
    public BizFaultModel detail(BizFaultModelParam bizFaultModelParam) {
        return this.queryBizFaultModel(bizFaultModelParam);
    }

    @Override
    public PageResult<Map<String, Object>> pageList(BizFaultModelParam param, Set<Integer> list) {
        return new PageResult<>(this.baseMapper.pageList(PageFactory.defaultPage(), param, list));
    }

    /**
     * 分页查询biz_fault_model
     *
     * @param param
     * @return
     */
    @Override
    public PageResult<Map<String, Object>> pageList(BizFaultModelParam param) {
        boolean isHasRole = LoginContextHolder.me().hasRole(SysRoleConstant.BUSINESS_MAINTENANCE);
        Set<Integer> set = new HashSet<>();
        PageResult<Map<String, Object>> pageResult = new PageResult<>();
        if (!isHasRole) {
            final Long sysLoginUserOrgId = LoginContextHolder.me().getSysLoginUserOrgId();
            final LambdaQueryWrapper<BizStation> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(BizStation::getOrgId, sysLoginUserOrgId);
            final List<BizStation> stationList = bizStationService.list(queryWrapper);
            for (BizStation bizStation : stationList) {
                final LambdaQueryWrapper<BizDevice> queryWrapper1 = new LambdaQueryWrapper<>();
                queryWrapper1.eq(BizDevice::getStationId, bizStation.getId());
                final List<BizDevice> deviceList = bizDeviceService.list(queryWrapper1);
                for (BizDevice bizDevice : deviceList) {
                    final Integer industryId = bizDevice.getIndustryId();
                    final BizIndustryInvolved industryInvolved = bizIndustryInvolvedService.getById(industryId);
                    if (ObjectUtil.isNotNull(industryInvolved)) {
                        final Integer groupId = industryInvolved.getGroupId();
                        set.add(groupId);
                    }
                }
            }
        }
        pageResult = new PageResult<>(baseMapper.pageList(PageFactory.defaultPage(), param, set));
        return pageResult;
    }

    /**
     * 根据算法模型id查询模型数据
     *
     * @param key
     * @return
     */
    @Override
    public BizFaultModel getOneByAccessToken(String key) {
        // 构造条件
        LambdaQueryWrapper<BizFaultModel> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BizFaultModel::getAccessToken, key);
        return this.baseMapper.selectOne(queryWrapper);
    }

    public List<BizFaultModel> getListByAccessToken(String key) {
        // 构造条件
        LambdaQueryWrapper<BizFaultModel> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BizFaultModel::getAccessToken, key);
        return this.baseMapper.selectList(queryWrapper);
    }

    public List<BizFaultModel> getListByAccessTokenForEdit(String key, Integer id) {
        // 构造条件
        LambdaQueryWrapper<BizFaultModel> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BizFaultModel::getAccessToken, key);
        queryWrapper.ne(BizFaultModel::getId, id);
        return this.baseMapper.selectList(queryWrapper);
    }

    /**
     * 获取biz_fault_model
     *
     * @author ssy
     * @since 2021/11/01 16:44
     */
    private BizFaultModel queryBizFaultModel(BizFaultModelParam bizFaultModelParam) {
        return this.getById(bizFaultModelParam.getId());
    }

    /**
     * 注册模型
     *
     * @param registerParam
     * @return
     */
    @Override
    public JSONObject register(RegisterParam registerParam) {
        String filePath = registerParam.getFilePath();
        String[] split = filePath.split(",");
        File[] files = new File[split.length];
        Map<String, Object> map = Maps.newHashMap();
        for (int i = 0; i < split.length; i++) {
            String path = MyFileUtils.getUploadPath() + "/" + split[i];
            File file = FileUtil.file(path);
            boolean exists = file.exists();
            if (!exists) {
                map.put("code", 500);
                map.put("message", "文件不存在");
                log.info(map.toString());
                return JSONUtil.parseObj(map);
            } else {
                files[i] = file;
            }
        }
        String post = EngineUtil.register(registerParam.getAccessToken(), registerParam.getGroupId(), files);
        return JSONUtil.parseObj(post);
    }

    /**
     * 根据异常名称获取模型
     *
     * @param bizFaultModelParam
     * @return
     */
    @Override
    public BizFaultModel getBizFaultModel(BizFaultModelParam bizFaultModelParam) {
        QueryWrapper<BizFaultModel> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("fault_name", bizFaultModelParam.getFaultName());
        queryWrapper.last("limit 1");
        return this.getOne(queryWrapper);
    }

    /**
     * 注册采集端模型
     *
     * @param registerParam
     * @return
     */
    @Override
    public ResponseData registerCollectModel(RegisterParam registerParam) {
        String collectUrl = "http://" + registerParam.getCollectoeIp() + ":8888";
        String fileIds = registerParam.getFileIds();
        String[] split = fileIds.split(",");
        File[] files = new File[split.length];
        for (int i = 0; i < split.length; i++) {
            SysFileInfoResult fileInfoResult = sysFileInfoService.getFileInfoResult(Long.valueOf(split[i]));
            String path = MyFileUtils.getUploadPath() + "/" + fileInfoResult.getFileBucket() + "/" + fileInfoResult.getFileObjectName();
            File file = FileUtil.file(path);
            boolean exists = file.exists();
            if (!exists) {
                return new ErrorResponseData(500, "文件不存在");
            } else {
                files[i] = file;
            }
        }

        String post = CollectorConfigUtil.register(collectUrl, registerParam.getAccessToken(), registerParam.getGroupId(), files);
        JSONObject parseObj = JSONUtil.parseObj(post);
        log.info("采集端注册模型结果：{}", post);
        if (parseObj.get("code").equals("200")) {
            return new SuccessResponseData();
        } else {
            return new ErrorResponseData(500, "采集端注册模型失败");
        }
    }
}
